Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ

Node / meshtastic / Meshtastic-Android / files / feature / firmware / src / commonTest / kotlin / org / meshtastic / feature / firmware / CommonPerformUsbUpdateTest.kt

Displaying Raw β€’ Download

feature/firmware/src/commonTest/kotlin/org/meshtastic/feature/firmware/CommonPerformUsbUpdateTest.kt 9fa9f1e341ee8d2c8fd9fabf9253b2f012fc8c95 (9fa9f1e3) Text, 11.68 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tf0883e@fileTb4b4b4:Te6edf3SuppressTb4b4b4(Ta5d6ff"Ta5d6ffMagicNumberTa5d6ff"Tb4b4b4)

Tff7b72package T7ee787org.meshtastic.feature.firmware

Tff7b72import T7ee787kotlinx.coroutines.test.runTest
Tff7b72import T7ee787org.meshtastic.core.common.util.CommonUri
Tff7b72import T7ee787org.meshtastic.core.database.entity.FirmwareRelease
Tff7b72import T7ee787org.meshtastic.core.model.DeviceHardware
Tff7b72import T7ee787org.meshtastic.core.testing.FakeNodeRepository
Tff7b72import T7ee787org.meshtastic.core.testing.FakeRadioController
Tff7b72import T7ee787org.meshtastic.core.testing.TestDataFactory
Tff7b72import T7ee787kotlin.test.Test
Tff7b72import T7ee787kotlin.test.assertIs
Tff7b72import T7ee787kotlin.test.assertNotNull
Tff7b72import T7ee787kotlin.test.assertNull
Tff7b72import T7ee787kotlin.test.assertTrue

T8b949e/**
* Tests for [performUsbUpdate] β€” the top-level internal function that handles USB/UF2 firmware updates.
*
* This class is `abstract` because it creates [CommonUri] instances via [CommonUri.parse], which on Android delegates
* to `android.net.Uri` and therefore requires Robolectric. Platform subclasses in `androidHostTest` and `jvmTest` apply
* the necessary runner configuration.
*/
Tff7b72abstract Tff7b72class T56d364CommonPerformUsbUpdateTest Tb4b4b4{

Tff7b72private Tff7b72val Te6edf3testRelease Tff7b72= Te6edf3FirmwareReleaseTb4b4b4(Te6edf3id Tff7b72= Ta5d6ff"Ta5d6ffv2.7.17Ta5d6ff"Tb4b4b4, Te6edf3zipUrl Tff7b72= Ta5d6ff"Ta5d6ffhttps://example.com/fw.zipTa5d6ff"Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3testHardware Tff7b72=
Te6edf3DeviceHardwareTb4b4b4(Te6edf3hwModelSlug Tff7b72= Ta5d6ff"Ta5d6ffRPI_PICOTa5d6ff"Tb4b4b4, Te6edf3platformioTarget Tff7b72= Ta5d6ff"Ta5d6ffpicoTa5d6ff"Tb4b4b4, Te6edf3architecture Tff7b72= Ta5d6ff"Ta5d6ffrp2040Ta5d6ff"Tb4b4b4)

T8b949e// ── firmwareUri != null (user-selected file) ────────────────────────────

Tf0883e@Test
Tff7b72fun Td2a8ff`user-selected file emits Downloading then Processing then AwaitingFileSave`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3firmwareUri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///tmp/firmware-pico-2.7.17.uf2Ta5d6ff"Tb4b4b4)

Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Te6edf3firmwareUriTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3statesTb4b4b4.Te6edf3size Tff7b72>Tff7b72= T79c0ff3Tb4b4b4, Ta5d6ff"Ta5d6ffExpected at least 3 state transitions, got Tffd700${Te6edf3statesTb4b4b4.Te6edf3sizeTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3DownloadingTff7b72>Tb4b4b4(Te6edf3statesTff7b72[T79c0ff0Tff7b72]Tb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3ProcessingTff7b72>Tb4b4b4(Te6edf3statesTff7b72[T79c0ff1Tff7b72]Tb4b4b4)
Te6edf3assertIsTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3AwaitingFileSaveTff7b72>Tb4b4b4(Te6edf3statesTff7b72[T79c0ff2Tff7b72]Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`user-selected file returns null - no cleanup artifact`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3firmwareUri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///tmp/firmware.uf2Ta5d6ff"Tb4b4b4)

Tff7b72val Te6edf3result Tff7b72=
Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Te6edf3firmwareUriTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertNullTb4b4b4(Te6edf3resultTb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`user-selected file extracts filename from URI path`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff1Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3firmwareUri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///storage/firmware-pico-2.7.17.uf2Ta5d6ff"Tb4b4b4)

Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Te6edf3firmwareUriTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3awaitingState Tff7b72= Te6edf3statesTb4b4b4.Te6edf3filterIsInstanceTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3AwaitingFileSaveTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3awaitingStateTb4b4b4.Te6edf3fileNameTb4b4b4.Te6edf3endsWithTb4b4b4(Ta5d6ff"Ta5d6ff.uf2Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffExpected filename to end with .uf2, got: Tffd700${Te6edf3awaitingStateTb4b4b4.Te6edf3fileNameTffd700}Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

T8b949e// ── firmwareUri == null (download path) ─────────────────────────────────

Tf0883e@Test
Tff7b72fun Td2a8ff`download path emits Error when retriever returns null`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3result Tff7b72=
Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72null Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertNullTb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3assertTrueTb4b4b4(
Te6edf3statesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657it Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Error Tb4b4b4}Tb4b4b4,
Ta5d6ff"Ta5d6ffExpected an Error state when retriever returns nullTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`download path emits AwaitingFileSave when retriever succeeds`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3artifact Tff7b72=
Te6edf3FirmwareArtifactTb4b4b4(
Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///tmp/firmware-pico-2.7.17.uf2Ta5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3fileName Tff7b72= Ta5d6ff"Ta5d6fffirmware-pico-2.7.17.uf2Ta5d6ff"Tb4b4b4,
Te6edf3isTemporary Tff7b72= Tff7b72trueTb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3result Tff7b72=
Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3onProgress Tff7b72-Tff7b72>
Te6edf3onProgressTb4b4b4(T79c0ff0.5fTb4b4b4)
Te6edf3onProgressTb4b4b4(T79c0ff1.0fTb4b4b4)
Te6edf3artifact
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertNotNullTb4b4b4(Te6edf3resultTb4b4b4)
Tff7b72val Te6edf3awaitingState Tff7b72= Te6edf3statesTb4b4b4.Te6edf3filterIsInstanceTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3AwaitingFileSaveTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3awaitingStateTb4b4b4.Te6edf3fileName Tff7b72=Tff7b72= Ta5d6ff"Ta5d6fffirmware-pico-2.7.17.uf2Ta5d6ff"Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`download path reports progress percentages during download`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3artifact Tff7b72=
Te6edf3FirmwareArtifactTb4b4b4(Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///tmp/fw.uf2Ta5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3fileName Tff7b72= Ta5d6ff"Ta5d6fffw.uf2Ta5d6ff"Tb4b4b4, Te6edf3isTemporary Tff7b72= Tff7b72trueTb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)

Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3onProgress Tff7b72-Tff7b72>
Te6edf3onProgressTb4b4b4(T79c0ff0.25fTb4b4b4)
Te6edf3onProgressTb4b4b4(T79c0ff0.75fTb4b4b4)
Te6edf3artifact
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Tff7b72val Te6edf3downloadingStates Tff7b72= Te6edf3statesTb4b4b4.Te6edf3filterIsInstanceTff7b72<Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3DownloadingTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3downloadingStatesTb4b4b4.Te6edf3size Tff7b72>Tff7b72= T79c0ff2Tb4b4b4, Ta5d6ff"Ta5d6ffExpected multiple Downloading states for progress updatesTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3downloadingStatesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3progressStateTb4b4b4.Te6edf3details Tff7b72=Tff7b72= Ta5d6ff"Ta5d6ff25%Ta5d6ff" Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffExpected 25% progress detailTa5d6ff"Tb4b4b4)
Te6edf3assertTrueTb4b4b4(Te6edf3downloadingStatesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3progressStateTb4b4b4.Te6edf3details Tff7b72=Tff7b72= Ta5d6ff"Ta5d6ff75%Ta5d6ff" Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffExpected 75% progress detailTa5d6ff"Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`download path returns artifact for caller cleanup`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3artifact Tff7b72=
Te6edf3FirmwareArtifactTb4b4b4(Te6edf3uri Tff7b72= Te6edf3CommonUriTb4b4b4.Te6edf3parseTb4b4b4(Ta5d6ff"Ta5d6fffile:///tmp/fw.uf2Ta5d6ff"Tb4b4b4)Tb4b4b4, Te6edf3fileName Tff7b72= Ta5d6ff"Ta5d6fffw.uf2Ta5d6ff"Tb4b4b4, Te6edf3isTemporary Tff7b72= Tff7b72trueTb4b4b4)

Tff7b72val Te6edf3result Tff7b72=
Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Te6edf3artifact Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertNotNullTb4b4b4(Te6edf3resultTb4b4b4, Ta5d6ff"Ta5d6ffShould return artifact for caller cleanupTa5d6ff"Tb4b4b4)
Tb4b4b4}

T8b949e// ── Error handling ──────────────────────────────────────────────────────

Tf0883e@Test
Tff7b72fun Td2a8ff`exception during update emits Error state`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

Tff7b72val Te6edf3states Tff7b72= Te6edf3mutableListOfTff7b72<Te6edf3FirmwareUpdateStateTff7b72>Tb4b4b4(Tb4b4b4)

Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{ Te6edf3statesTb4b4b4.Te6edf3addTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72throw Te6edf3RuntimeExceptionTb4b4b4(Ta5d6ff"Ta5d6ffDownload failedTa5d6ff"Tb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3assertTrueTb4b4b4(Te6edf3statesTb4b4b4.Te6edf3any Tb4b4b4{ Tffa657it Tff7b72is Te6edf3FirmwareUpdateStateTb4b4b4.Te6edf3Error Tb4b4b4}Tb4b4b4, Ta5d6ff"Ta5d6ffExpected Error state on exceptionTa5d6ff"Tb4b4b4)
Tb4b4b4}

Tf0883e@Test
Tff7b72fun Td2a8ff`exception returns cleanup artifact when download partially completed`Tb4b4b4(Tb4b4b4) Tff7b72= Te6edf3runTest Tb4b4b4{
Tff7b72val Te6edf3radioController Tff7b72= Te6edf3FakeRadioControllerTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3nodeRepository Tff7b72= Te6edf3FakeNodeRepositoryTb4b4b4(Tb4b4b4)
Te6edf3nodeRepositoryTb4b4b4.Te6edf3setMyNodeInfoTb4b4b4(Te6edf3TestDataFactoryTb4b4b4.Te6edf3createMyNodeInfoTb4b4b4(Te6edf3myNodeNum Tff7b72= T79c0ff4T79c0ff2Tb4b4b4)Tb4b4b4)

T8b949e// The retriever provides a file, but then something after (rebootToDfu) throws.
T8b949e// In this test, since rebootToDfu on FakeRadioController is a no-op, we need to
T8b949e// simulate failure differently. Instead, we throw during the retrieval.
Tff7b72val Te6edf3result Tff7b72=
Te6edf3performUsbUpdateTb4b4b4(
Te6edf3release Tff7b72= Te6edf3testReleaseTb4b4b4,
Te6edf3hardware Tff7b72= Te6edf3testHardwareTb4b4b4,
Te6edf3firmwareUri Tff7b72= Tff7b72nullTb4b4b4,
Te6edf3radioController Tff7b72= Te6edf3radioControllerTb4b4b4,
Te6edf3nodeRepository Tff7b72= Te6edf3nodeRepositoryTb4b4b4,
Te6edf3updateState Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4,
Te6edf3retrieveUsbFirmware Tff7b72= Tb4b4b4{ Te6edf3_Tb4b4b4, Te6edf3_Tb4b4b4, Te6edf3_ Tff7b72-Tff7b72> Tff7b72throw Te6edf3RuntimeExceptionTb4b4b4(Ta5d6ff"Ta5d6ffNetwork errorTa5d6ff"Tb4b4b4) Tb4b4b4}Tb4b4b4,
Tb4b4b4)

T8b949e// cleanupArtifact is null when the error happens before retriever returns
Te6edf3assertNullTb4b4b4(Te6edf3resultTb4b4b4, Ta5d6ff"Ta5d6ffNo cleanup artifact when retriever throwsTa5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.08s